package com.gzsxy.esjy.feign;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * @author xiaolong
 * @version 1.0
 * @description: Condition是个接口，需要实现matches方法，返回true则注入bean，false则不注入。
 * @date 2021/10/14 9:46
 */
@Slf4j
@Component
public class FeignClientCondition implements Condition {

    private static List<String> WHITE_LIST = null;


    /**
     * @param name 服务名
     * @return
     * @description: 初始化
     */
    private void init(String name) {
        if (WHITE_LIST != null) {
            return;
        }
        PathMatchingResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver();
        try {
            //获取资源信息
            Resource[] resources = resourceLoader.getResources("classpath*:feign-white-list.json");
            for (Resource resource : resources) {
                if (WHITE_LIST == null) {
                    InputStream inputStream = resource.getInputStream();
                    //转为map对象
                    Map<String, List<String>> map = JSON.parseObject(inputStream, Map.class);
                    log.info("{} 远程调用白名单信息{}", name, JSON.toJSON(map));
                    //获取该服务下所需要调用feign的服务名
                    List<String> list = map.get(name);
                    if (list != null) {
                        WHITE_LIST = list;
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //返回true则注入bean，false则不注入。
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //conditionContext.getEnvironment()获取当前环境信息， 获取服务名
        String applicationName = conditionContext.getEnvironment().getProperty("spring.application.name");
        //初始化map
        init(applicationName);
        //获取指定路径注解的信息
        MultiValueMap<String, Object> allAnnotationAttributes = annotatedTypeMetadata.getAllAnnotationAttributes("org.springframework.cloud.openfeign.FeignClient");
        //获取value属性值（调用feign注解中的value属性值为被调用方的服务名）
        String feignName = (String) allAnnotationAttributes.getFirst("value");
        if (applicationName.equals(feignName)) {
            log.error("[{}]服务无权限依赖feign-sdk:{},如需要配置请在feign-white-list.json添加", applicationName, feignName);
            return false;
        }
        if (WHITE_LIST == null) {
            log.error("[{}] 服务依赖权限配置为空，如需要配置请在feign-white-list.json添加", applicationName);
            return false;
        }
        if (WHITE_LIST.contains(feignName)) {
            return true;
        }
        log.error("[{}] 服务无权限依赖feign-sdk:{},如需要配置请在feign-white-list.json添加", applicationName, feignName);
        return false;
    }
}
